#include <nxos.h>

#define PSFLAG_THREAD 0x01

NX_PRIVATE char * threadState[] = {
    "    INIT",
    "   READY",
    " RUNNING",
    " BLOCKED",
    "    EXIT",
};

NX_PRIVATE NX_Error GetThreadSnapshot()
{
    NX_Error err = NX_EOK;
    NX_SnapshotThread snapshotInfo;

    NX_Solt solt = NX_SnapshotCreate(NX_SNAPSHOT_THREAD, 0);
    if (solt == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("Create snapshot failed!");
        return err;
    }

    NX_Printf("     TID      PID   ON_CPU  CPU_AFF    STATE FIX_PRIO     PRIO     NAME\r\n");
    if ((err = NX_SnapshotFirst(solt, (void *)&snapshotInfo)) == NX_EOK)
    {
        do
        {
            NX_Printf("%8d %8d %8d %8d %s %8d %8d     %s\r\n", snapshotInfo.threadId, snapshotInfo.ownerProcessId,
                      snapshotInfo.onCore, snapshotInfo.coreAffinity,
                      threadState[snapshotInfo.state], snapshotInfo.fixedPriority, snapshotInfo.priority,
                      snapshotInfo.name);
        } while((err = NX_SnapshotNext(solt, (void *)&snapshotInfo)) == NX_EOK);
    }

    NX_SoltClose(solt);
    return NX_EOK;
}

NX_PRIVATE NX_Error GetProcessSnapshot()
{
    NX_Error err = NX_EOK;
    NX_SnapshotProcess snapshotInfo;

    NX_Solt solt = NX_SnapshotCreate(NX_SNAPSHOT_PROCESS, 0);
    if (solt == NX_SOLT_INVALID_VALUE)
    {
        NX_Printf("Create snapshot failed!");
        return err;
    }

    NX_Printf("     PID     PPID  THREADS  COMMAND\r\n");
    if ((err = NX_SnapshotFirst(solt, (void *)&snapshotInfo)) == NX_EOK)
    {
        do
        {
            NX_Printf("%8d %8d %8d  %s\r\n", snapshotInfo.processId, snapshotInfo.parentProcessId,
                      snapshotInfo.threadCount, snapshotInfo.exePath);
        } while((err = NX_SnapshotNext(solt, (void *)&snapshotInfo)) == NX_EOK);
    }

    NX_SoltClose(solt);
    return NX_EOK;
}

NX_Error PowerBoxBuiltinPs(int argc, char *argv[], char * env)
{
    int flag = 0;
	int i;

	for(i = 1; i < argc; i++)
	{
		if (NX_StrCmp(argv[i], "-a") == 0)
        {
			flag |= PSFLAG_THREAD;
        }
        else if (NX_StrCmp(argv[i], "-h") == 0)
        {
			NX_Printf("usage:\r\n      ps [-a] process or thread state\r\n");
            return NX_EOK;
        }
	}

    if (flag & PSFLAG_THREAD)
    {
        GetThreadSnapshot();
    }
    else
    {
        GetProcessSnapshot();
    }
    NX_Printf("\r\n");
    return NX_EOK;
}
